package com.jdd.modules.parkmonthly.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jdd.common.api.vo.Result;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.exception.JddException;
import com.jdd.common.system.vo.LoginUser;
import com.jdd.common.util.DateUtil;
import com.jdd.common.util.LoginUserUtils;
import com.jdd.common.util.MonthlyUploadHttpUtils;
import com.jdd.common.util.SnowFlakeUtil;
import com.jdd.modules.configcartype.entity.ConfigCarType;
import com.jdd.modules.configcartype.service.IConfigCarTypeService;
import com.jdd.modules.parkcar.entity.ParkCarMonthly;
import com.jdd.modules.parkcar.entity.ParkSpace;
import com.jdd.modules.parkcar.service.IParkCarMonthlyService;
import com.jdd.modules.parkcar.service.IParkSpaceService;
import com.jdd.modules.parking.entity.ParkCarEnterLog;
import com.jdd.modules.parking.service.IparkCarEnterLogService;
import com.jdd.modules.parkmonthly.dto.MonthlyCarDto;
import com.jdd.modules.parkmonthly.dto.MonthlyCardDelayDto;
import com.jdd.modules.parkmonthly.dto.TurnCardVo;
import com.jdd.modules.parkmonthly.entity.*;
import com.jdd.modules.parkmonthly.mapper.MonthlyCardInfoMapper;
import com.jdd.modules.parkmonthly.service.*;
import com.jdd.modules.parkmonthly.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Description: 月卡信息表
 * @Author: jdd
 * @Date: 2021-11-09
 * @Version: V1.0
 */
@Service
@Slf4j
@Lazy
public class TaskMonthlyCardInfoServiceImpl extends ServiceImpl<MonthlyCardInfoMapper, MonthlyCardInfo> implements ITaskMonthlyCardInfoService {


    @Resource
    MonthlyUploadHttpUtils monthlyUploadHttpUtils;
    @Resource
    private IMonthlyCarTypeConvertService iMonthlyCarTypeConvertService;
    @Resource
    private IMonthlyPackageInfoService iMonthlyPackageInfoService;
    @Resource
    private IMonthlyCardEditInfoService iMonthlyCardEditInfoService;
    @Resource
    private IparkCarEnterLogService iparkCarEnterLogService;

    @Resource
    private IParkCarMonthlyService iParkCarMonthlyService;
    @Resource
    private IMonthlyCardInfoService iMonthlyCardInfoService;
    @Resource
    private IParkSpaceService parkSpaceService;

    @Resource
    private IMonthlyCarTypeConvertService monthlyCarTypeConvertService;

    @Resource
    private IConfigCarTypeService configCarTypeService;


    /**
     * 处理在场车辆信息
     *
     * @param parkSpaces
     * @param plateNoList
     * @param monthlyCardInfo
     * @return
     */
    private Result dealInParkCar(List<ParkSpace> parkSpaces, List<String> plateNoList, MonthlyCardInfo monthlyCardInfo, EditMonthlyCardsVO editMonthlyCardsVO) {
        // 新增月租车信息
        List<ParkCarMonthly> list = getParkCarMonthlyEntity(parkSpaces, plateNoList, monthlyCardInfo);
        boolean addResult = iParkCarMonthlyService.saveBatch(list);
        editMonthlyCardsVO.setAddParkCarMonthly(list);
        if (!addResult) {
            log.error("新增月租车信息失败！");
            return Result.error("新增月租车信息失败！");
        }
        if (monthlyCardInfo.getEndTime().equals(monthlyCardInfo.getBeginTime())) {
            log.info("月卡未开通具体时间！");
            return Result.ok("开通成功！");
        }
        // 查询绑定月租车
        QueryWrapper<ParkCarMonthly> parkCarMonthlyQueryWrapper = new QueryWrapper<>();
        parkCarMonthlyQueryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
        parkCarMonthlyQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
        List<ParkCarMonthly> parkCarMonthlyList = iParkCarMonthlyService.list(parkCarMonthlyQueryWrapper);
        // 获取绑定月租的车牌信息，区域信息
        List<String> plateNos = parkCarMonthlyList.stream().map(ParkCarMonthly::getPlateNo).distinct().collect(Collectors.toList());
        List<String> areaIds = parkCarMonthlyList.stream().map(ParkCarMonthly::getAreaId).distinct().collect(Collectors.toList());

        // 办卡时，查询勾选车位在场车辆信息(最近一条记录，且在指定的区域)
        List<ParkCarEnterLog> parkCarEnterLogs = getList(monthlyCardInfo.getParkCode(), plateNos, areaIds);
        log.info(" 办卡时，查询勾选车位在场车辆信息==================>:{}", parkCarEnterLogs);
        if (CollectionUtils.isEmpty(parkCarEnterLogs)) {

            return Result.ok("开通成功");
        }
        // 下次生效，不转卡
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            return Result.ok("开通成功");
        }
        QueryWrapper<ParkSpace> parkSpaceQueryWrapper = new QueryWrapper<>();
        parkSpaceQueryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
        parkSpaceQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
        parkSpaceQueryWrapper.eq("park_status", 0);
        List<ParkSpace> spaces = parkSpaceService.list(parkSpaceQueryWrapper);
        return addParkCarEnterInfo(monthlyCardInfo, spaces, parkCarEnterLogs, editMonthlyCardsVO);
    }

    /**
     * 车辆是否在场查询
     *
     * @param monthlyCarDto
     * @return
     */
    private List<String> queryCarIsInPark(MonthlyCarDto monthlyCarDto) {
        log.info("查询勾选的车位是否为场内车辆，传入参数--------------------------》:{}", monthlyCarDto);
        // 是否有在场车辆
        QueryWrapper<ParkCarEnterLog> parkCarEnterLogQueryWrapper = new QueryWrapper<>();
        parkCarEnterLogQueryWrapper.eq("is_out", JddConstant.StringNumber.STRING_ZERO);
        parkCarEnterLogQueryWrapper.eq("park_code", monthlyCarDto.getParkCode());
        if (CollectionUtils.isNotEmpty(monthlyCarDto.getPlateNoList())) {
            parkCarEnterLogQueryWrapper.in("plate_no", monthlyCarDto.getPlateNoList());
        }
        List<ParkCarEnterLog> parkCarEnterLogs = iparkCarEnterLogService.list(parkCarEnterLogQueryWrapper);
        log.info("查询勾选的车位的入场记录，查询结果为--------------------------》:{}", parkCarEnterLogs);
        List<String> plateNoList = parkCarEnterLogs.stream().map(ParkCarEnterLog::getPlateNo).distinct().collect(Collectors.toList());
        log.info("查询绑定月卡的车牌号，在场车辆的车牌号--------------------------》:{}", plateNoList);
        return plateNoList;
    }


    /**
     * 查询该月卡信息绑定的车位信息
     *
     * @param monthlyCardInfo
     * @return
     */
    @Override
    public Result getUpateCarPlaceInfo(MonthlyCardInfo monthlyCardInfo) {
        log.info("查询该月卡信息绑定的车位信息，传入参数-------------------------》:{}", monthlyCardInfo);
        Result<List<ParkSpace>> result = new Result<>();
        QueryWrapper<ParkSpace> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
        queryWrapper.eq("status", "Y");
        List<ParkSpace> parkSpaceList = parkSpaceService.list(queryWrapper);
        log.info("查询该月卡信息绑定的车位信息，parkSpaceList-------------------------》:{}", monthlyCardInfo);
        result.setSuccess(true);
        result.setResult(parkSpaceList);
        return result;
    }


    /**
     * 月卡注销
     *
     * @param monthlyCardInfo1
     * @return
     */
    @Override
    @CacheEvict(value = {"monthly:cardAndPackage"}, allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Result getMonthlyCardConcel(MonthlyCardInfo monthlyCardInfo1) {
        try {
            MonthlyCardConcelVO monthlyCardConcelVO = new MonthlyCardConcelVO();
            monthlyCardConcelVO.setMessageId(monthlyCardInfo1.getMessageId());
            log.info("注销月卡信息，传入参数--------------------------》:{}", monthlyCardInfo1);
            boolean resFlag = true;
            MonthlyCardInfo monthlyCardInfo = this.getById(monthlyCardInfo1.getId());
            monthlyCardInfo.setMonthlyMoney(monthlyCardInfo1.getMonthlyMoney());
            monthlyCardInfo.setRemark(monthlyCardInfo1.getRemark());
            QueryWrapper<MonthlyCarConfig> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
            MonthlyPackageInfo monthlyPackageInfo = iMonthlyPackageInfoService.getById(monthlyCardInfo.getPackageId());
            log.info("注销月卡信息，查询月套餐信息--------------------------》:{}", monthlyPackageInfo);
            // 判断是否有在场车辆
            List<ParkCarEnterLog> parkCarEnterLogs = getPlateNoInPark(monthlyCardInfo.getParkCode(), monthlyCardInfo.getId());
            List<ParkCarEnterLog> parkCarEnterLogList = new ArrayList<>();
            List<MonthlyCarTypeConvert> monthlyCarTypeConverts = new ArrayList<>();
            List<ParkCarEnterLog> isTransferCarEnterLogList = new ArrayList<>();
            log.info("查询在场记录信息为ssss--------------------------》:{}", parkCarEnterLogs);
            // 若存在入场记录，则生成一条注销时间的临时记录
            if (parkCarEnterLogs.size() > 0) {
                for (ParkCarEnterLog parkCarEnterLog : parkCarEnterLogs) {
                    // 若为欲转卡，直接出场
                    if ("1".equals(parkCarEnterLog.getIsTransfer())) {
                        parkCarEnterLog.setIsOut("1");
                        iparkCarEnterLogService.updateById(parkCarEnterLog);
                        isTransferCarEnterLogList.add(parkCarEnterLog);
                        continue;
                    }
                    // 如果是正常入场，且未获得车位，直接跳过
                    if("0".equals(parkCarEnterLog.getIsTransfer())&&StringUtils.isBlank(parkCarEnterLog.getParkNumber()))
                    {
                        continue;
                    }
                    parkCarEnterLog.setId(SnowFlakeUtil.getId());
                    parkCarEnterLog.setCarNature(JddConstant.StringNumber.STRING_ZERO);
                    // 判断月租是否过期,过期
                    if (monthlyCardInfo.getEndTime().before(new Date())) {
                        // 判断入场是否过期
                        if (DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()).before(monthlyCardInfo.getEndTime())) {
                            parkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(monthlyCardInfo.getEndTime()));
                        } else {
                            continue;
                        }
                    } else {
                        // 未过期
                        parkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(new Date()));
                    }
                    ConfigCarType configCarType = this.getCarType(parkCarEnterLog.getParkCode(), Integer.valueOf(parkCarEnterLog.getCarTypeNo()));
                    if (null != configCarType) {
                        parkCarEnterLog.setCarTypeId(configCarType.getId());
                        parkCarEnterLog.setCarTypeName(configCarType.getCarTypeName());
                    }
                    parkCarEnterLog.setParkNumber("");
                    parkCarEnterLog.setMonthlyCardId("");
                    parkCarEnterLog.setCreateTime(new Date());
                    //组装转卡记录
                    MonthlyCarTypeConvert monthlyCarTypeConvert = getMonthlyCarTypeConvert(monthlyCardInfo, parkCarEnterLog, monthlyPackageInfo);
                    monthlyCarTypeConverts.add(monthlyCarTypeConvert);
                    parkCarEnterLogList.add(parkCarEnterLog);
                }
                log.info("生成入场记录信息为--------------------------》:{}", parkCarEnterLogs);
                resFlag = iparkCarEnterLogService.saveBatch(parkCarEnterLogList);
                monthlyCardConcelVO.setParkCarEnterLogList(parkCarEnterLogList);
                if (!resFlag) {
                    return Result.error("新增转卡失败！");
                }
                resFlag = iMonthlyCarTypeConvertService.saveBatch(monthlyCarTypeConverts);
                monthlyCardConcelVO.setMonthlyCarTypeConverts(monthlyCarTypeConverts);
                monthlyCardConcelVO.setIsTransferCarEnterLogList(isTransferCarEnterLogList);

                if (!resFlag) {
                    return Result.error("新增转卡失败！");
                }
            }
            // 3.注销月卡信息
            monthlyCardInfo.setMonthlyStatus(JddConstant.IntNumber.INT_THREE);
            monthlyCardInfo.setUpdateTime(new Date());
            monthlyCardInfo.setUpdateUserId(monthlyCardInfo1.getUpdateUserId());
            monthlyCardInfo.setUpdateUserName(monthlyCardInfo1.getUpdateUserName());

            resFlag = this.updateById(monthlyCardInfo);
            monthlyCardConcelVO.setMonthlyCardInfo(monthlyCardInfo);


            if (!resFlag) {
                return Result.error("更新月卡为注销状态失败！");
            }
            // 4.还原车位绑定
            Result<List<ParkSpace>> result = getUpateCarPlaceInfo(monthlyCardInfo);
            List<ParkSpace> parkSpaceList = result.getResult();
            List<ParkSpace> parkSpaceLists = new LinkedList<>();
            if (parkSpaceList.size() > 0) {
                for (ParkSpace parkSpace : parkSpaceList) {
                    parkSpace.setParkStatus(JddConstant.StringNumber.STRING_ZERO);
                    parkSpace.setMonthlyCode("");
                    parkSpace.setAddress("");
                    parkSpace.setUserName("");
                    parkSpace.setMobile("");
                    parkSpace.setMonthlyCardId("");
                    parkSpace.setStartTime(null);
                    parkSpace.setEndTime(null);
                    parkSpace.setPlateNo("");
                    parkSpace.setParkStatus(JddConstant.StringNumber.STRING_ZERO);
                    resFlag = parkSpaceService.updateById(parkSpace);
                    parkSpaceLists.add(parkSpace);
                    if (!resFlag) {
                        return Result.error("更新车位失败！");
                    }
                }
            }
            monthlyCardConcelVO.setParkSpaceList(parkSpaceLists);

            // 5.月租车信息
            QueryWrapper<ParkCarMonthly> wrapper = new QueryWrapper<>();
            wrapper.eq("park_code", monthlyCardInfo.getParkCode());
            wrapper.eq("monthly_card_id", monthlyCardInfo.getId());
            iParkCarMonthlyService.remove(wrapper);
            // 6.新增月卡操作记录
            MonthlyCardEditInfo monthlyCardEditInfo = getMonthlyCardEditInfo(monthlyCardInfo, JddConstant.StringNumber.STRING_THREE);

            monthlyCardConcelVO.setMonthlyCardEditInfo(monthlyCardEditInfo);

            result = monthlyUploadHttpUtils.postMonthlyUpload("", monthlyCardConcelVO);
            if (200 != result.getCode()) {
                throw new JddException(500, result.getMessage());
            }
            return result;
        } catch (Exception e) {
            log.error("处理场端修改月卡信息出现异常,进行数据回滚!->{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            String messageId = monthlyCardInfo1.getMessageId();
            AddMonthlySpace addMonthlySpace = new AddMonthlySpace();
            addMonthlySpace.setStr(messageId);
            monthlyUploadHttpUtils.postMonthlyUpload("", addMonthlySpace);
            return Result.error("月卡修改信息失败!");
        }

    }

    private List<ParkCarMonthly> getParkCarMonthly(MonthlyCardDelayDto monthlyCardDelayDto) {
        QueryWrapper<ParkCarMonthly> parkCarMonthlyQueryWrapper = new QueryWrapper<>();
        parkCarMonthlyQueryWrapper.eq("park_code", monthlyCardDelayDto.getParkCode());
        parkCarMonthlyQueryWrapper.eq("monthly_card_id", monthlyCardDelayDto.getMonthlyCardId());
        parkCarMonthlyQueryWrapper.eq("status", "Y");
        List<ParkCarMonthly> parkCarMonthlys = iParkCarMonthlyService.list(parkCarMonthlyQueryWrapper);
        log.info("办理月卡延期，月租车信息------------------------------》:{}", parkCarMonthlys);
        return parkCarMonthlys;
    }

    private List<ParkSpace> getParkSpace(MonthlyCardDelayDto monthlyCardDelayDto) {
        QueryWrapper<ParkSpace> parkSpaceQueryWrapper = new QueryWrapper<>();
        parkSpaceQueryWrapper.eq("park_code", monthlyCardDelayDto.getParkCode());
        parkSpaceQueryWrapper.eq("status", "Y");
        parkSpaceQueryWrapper.eq("monthly_card_id", monthlyCardDelayDto.getMonthlyCardId());
        List<ParkSpace> parskSpace = parkSpaceService.list(parkSpaceQueryWrapper);
        log.info("办理月卡延期，查询绑定车位信息------------------------------》:{}", parskSpace);
        return parskSpace;
    }


    /**
     * 获取识别类型对应的车辆类型
     */
    @Override
    public ConfigCarType getCarType(String parkCode, int type) {
        QueryWrapper<ConfigCarType> configCarTypeQueryWrapper = new QueryWrapper<>();
        configCarTypeQueryWrapper.eq("park_code", parkCode);
        List<ConfigCarType> configCarTypeList = configCarTypeService.list(configCarTypeQueryWrapper);
        for (ConfigCarType configCarType : configCarTypeList) {
            List<String> list = Arrays.asList(configCarType.getCarTypeNo().split(","));
            if (list.contains(String.valueOf(type))) {
                return configCarType;
            }
        }
        return null;
    }


    /**
     * 最近的一条入场记录，是否在指定区域内
     *
     * @param parkCode
     * @param plateNos
     * @param areaList
     * @return
     */
    @Override
    public List<ParkCarEnterLog> getList(String parkCode, List<String> plateNos, List<String> areaList) {
        QueryWrapper<ParkCarEnterLog> parkCarEnterLogQueryWrapper = new QueryWrapper<>();
        parkCarEnterLogQueryWrapper.eq("park_code", parkCode);
        parkCarEnterLogQueryWrapper.eq("is_out", JddConstant.StringNumber.STRING_ZERO);
        parkCarEnterLogQueryWrapper.eq("enter_type", 0);
        parkCarEnterLogQueryWrapper.in("plate_no", plateNos);
        parkCarEnterLogQueryWrapper.orderByAsc("car_enter_time");
        List<ParkCarEnterLog> parkCarEnterLogList = iparkCarEnterLogService.list(parkCarEnterLogQueryWrapper);
        log.info("办理月卡延期，是否有在场的信息------------------------------》:{}", parkCarEnterLogList);
        Map<String, ParkCarEnterLog> newMap = new HashMap(16);
        for (ParkCarEnterLog parkCarEnterLog : parkCarEnterLogList) {
            newMap.put(parkCarEnterLog.getPlateNo(), parkCarEnterLog);
        }
        List<ParkCarEnterLog> carEnterLogs = new ArrayList<>();
        for (String key : newMap.keySet()) {
            carEnterLogs.add(newMap.get(key));
        }
        List<ParkCarEnterLog> enterLogList = new ArrayList<>();
        for (ParkCarEnterLog parkCarEnterLog : carEnterLogs) {
            if (areaList.contains(parkCarEnterLog.getAreaId())) {
                enterLogList.add(parkCarEnterLog);
            }
        }
        List<ParkCarEnterLog> parkCarEnterLogs = enterLogList.stream()
                .sorted(Comparator.comparing(ParkCarEnterLog::getCarEnterTime))
                .collect(Collectors.toList());
        return parkCarEnterLogs;
    }

    /**
     * 处理跳延时，在场记录的处理
     *
     * @param monthlyCardInfo
     * @param parkCarEnterLog
     * @param newMonthlyCardInfo
     */
    private void dealDelayLogs(List<ParkCarEnterLog> parkCarEnterLogList, MonthlyCardInfo newMonthlyCardInfo, ParkCarEnterLog parkCarEnterLog, MonthlyCardInfo monthlyCardInfo, MonthlyPackageInfo packageInfo) {
        // 跳延,入场时间在月卡结束时间之后，并在新月卡开始之后，新增转卡记录，月租车入场，入场时间+1s
        if (monthlyCardInfo.getEndTime().before(DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()))
                && newMonthlyCardInfo.getBeginTime().before(DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()))) {
            parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
            String time = DateUtil.addSecond(parkCarEnterLog.getCarEnterTime(), JddConstant.IntNumber.INT_ONE);
            parkCarEnterLog.setCarEnterTime(time);
            parkCarEnterLog.setMonthlyCardId(monthlyCardInfo.getId());
            iparkCarEnterLogService.save(parkCarEnterLog);
            parkCarEnterLogList.add(parkCarEnterLog);
        }
        // 跳延,入场时间在月卡结束时间之后，并在新月卡开始之前，新增欲转卡记录，月租车入场，入场时间新月租开始时间
        else if (monthlyCardInfo.getEndTime().before(DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()))
                && newMonthlyCardInfo.getBeginTime().after(DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()))) {
            parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_ONE);
            parkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(newMonthlyCardInfo.getBeginTime()));
            parkCarEnterLog.setMonthlyCardId(monthlyCardInfo.getId());
            iparkCarEnterLogService.save(parkCarEnterLog);
            parkCarEnterLogList.add(parkCarEnterLog);

        }
        // 跳延,入场时间在月卡结束时间之前，插入两条记录，补一条临时车入场记录,入场时间为旧月卡结束时间，补一条月卡入场记录
        else {
            // 补临时车入场
            parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
            parkCarEnterLog.setCarNature(JddConstant.StringNumber.STRING_ZERO);
            parkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(monthlyCardInfo.getEndTime()));
            parkCarEnterLog.setMonthlyCardId("");
            ConfigCarType configCarType = this.getCarType(parkCarEnterLog.getParkCode(), Integer.valueOf(parkCarEnterLog.getCarTypeNo()));
            if (null != configCarType) {
                parkCarEnterLog.setCarTypeId(configCarType.getId());
                parkCarEnterLog.setCarTypeName(configCarType.getCarTypeName());
            }
            // 月租车入场记录 parkCarEnterLog;
            ParkCarEnterLog newParkCarEnterLog = new ParkCarEnterLog();
            BeanUtils.copyProperties(parkCarEnterLog, newParkCarEnterLog);
            newParkCarEnterLog.setId(SnowFlakeUtil.getId());
            newParkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(newMonthlyCardInfo.getBeginTime()));
            newParkCarEnterLog.setCarNature(JddConstant.StringNumber.STRING_ONE);
            newParkCarEnterLog.setCarTypeName(packageInfo.getMonthlyTypeName());
            newParkCarEnterLog.setMonthlyCardId(monthlyCardInfo.getId());
            newParkCarEnterLog.setCarTypeId(packageInfo.getMonthlyTypeId());
            // 今天在新月卡之前，补欲转卡（不知何时出场）
            if (new Date().before(newMonthlyCardInfo.getBeginTime())) {
                newParkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_ONE);
            } else {
                // 今天在新月卡之前，补欲转卡
                newParkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
            }
            // 临时车入场不需要分配车位
            parkCarEnterLog.setParkNumber("");
            iparkCarEnterLogService.save(parkCarEnterLog);
            iparkCarEnterLogService.save(newParkCarEnterLog);
            parkCarEnterLogList.add(parkCarEnterLog);
            parkCarEnterLogList.add(newParkCarEnterLog);
        }
    }

    /**
     * 处理同一车牌号，多个入场记录，只分配一个车位,月租车
     *
     * @param parkSpaces
     * @param parkCarEnterLog
     * @param count
     * @param areaList
     */
    private Integer dealSamePlateNoPlace(List<ParkSpace> parkSpaces, ParkCarEnterLog parkCarEnterLog, int count, List<String> areaList, MonthlyCardInfo monthlyCardInfo, List<ParkSpace> listParkSpace) {
        ParkSpace parkSpace = null;

        List<ParkSpace> plateNoAndParkSpace = parkSpaces.stream().filter(ite -> parkCarEnterLog.getPlateNo().equals(ite.getPlateNo()) && parkCarEnterLog.getAreaId().equals(ite.getAreaId())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(plateNoAndParkSpace)) {
            parkSpace = plateNoAndParkSpace.get(0);
        } else {
            List<ParkSpace> parkSpacess = parkSpaces.stream().filter(ite -> "0".equals(ite.getParkStatus() )&& parkCarEnterLog.getAreaId().equals( ite.getAreaId())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(parkSpacess)){
                parkSpace = parkSpacess.get(0);
            }
        }
        if (null==parkSpace){
            return 0;
        }
        parkSpace.setPlateNo(parkCarEnterLog.getPlateNo());
        parkSpace.setMonthlyCode(monthlyCardInfo.getMonthlyCode());
        parkSpace.setMonthlyCardId(monthlyCardInfo.getId());
        parkSpace.setParkStatus("1");
        parkSpaceService.updateById(parkSpace);
        listParkSpace.add(parkSpace);
        parkSpaces.remove(parkSpace);

        QueryWrapper<ParkCarEnterLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("park_code", parkCarEnterLog.getParkCode());
        queryWrapper.eq("plate_no", parkCarEnterLog.getPlateNo());
        queryWrapper.eq("car_nature", "1");
        queryWrapper.in("area_id", areaList);
        queryWrapper.orderByDesc("create_time");
        List<ParkCarEnterLog> logList = iparkCarEnterLogService.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(logList)) {
            parkCarEnterLog.setParkNumber(logList.get(0).getParkNumber());
            return count;
        } else {
            parkCarEnterLog.setParkNumber(parkSpace.getParkNumber());
            return count + 1;
        }
    }


    /**
     * 删除的关联车牌号的的月租车信息
     *
     * @param
     * @return
     */
    public void deletePlateNo(List<String> plateNos, MonthlyCardInfo monthlyCardInfo, EditMonthlyCardsVO editMonthlyCardsVO) {
        // 删除租车信息
        log.info("删除关联车位信息，传入参数--------------------------》:{}", plateNos);
        QueryWrapper<ParkCarMonthly> parkCarMonthlyQueryWrapper = new QueryWrapper<>();
        parkCarMonthlyQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
        parkCarMonthlyQueryWrapper.in("plate_no", plateNos);
        List<ParkCarMonthly> parkCarMonthlyList = iParkCarMonthlyService.list(parkCarMonthlyQueryWrapper);
        List<String> araIds = parkCarMonthlyList.stream().map(ParkCarMonthly::getAreaId).distinct().collect(Collectors.toList());
        // 获取删除的场内车辆月租车入场记录
        List<ParkCarEnterLog> fieldParkCarEnterLog = getList(monthlyCardInfo.getParkCode(), plateNos, araIds);
        log.info("删除的场内车辆月租车牌号的入场记录为---------:{}", fieldParkCarEnterLog);
        if (CollUtil.isNotEmpty(fieldParkCarEnterLog)) {
            MonthlyPackageInfo monthlyPackageInfo = iMonthlyPackageInfoService.getById(monthlyCardInfo.getPackageId());
            List<ParkCarEnterLog> parkCarEnterLogs = new ArrayList<>();
            List<MonthlyCarTypeConvert> monthlyCarTypeConverts = new ArrayList<>();
            List<ParkSpace> parkSpaceList = new LinkedList<>();
            for (ParkCarEnterLog parkCarEnterLog : fieldParkCarEnterLog) {
                // 修改车牌号，删除原有车牌号的车位
                if (StringUtils.isNotEmpty(parkCarEnterLog.getParkNumber())) {
                    QueryWrapper<ParkSpace> queryWrapper1 = new QueryWrapper<>();
                    queryWrapper1.eq("monthly_card_id", monthlyCardInfo.getId());
                    queryWrapper1.eq("plate_no", parkCarEnterLog.getPlateNo());
                    queryWrapper1.eq("park_number", parkCarEnterLog.getParkNumber());
                    ParkSpace parkSpace = parkSpaceService.getOne(queryWrapper1);
                    parkSpace.setParkStatus("0");
                    parkSpace.setPlateNo("");
                    parkSpaceService.updateById(parkSpace);
                    parkSpaceList.add(parkSpace);
                }
                ParkCarEnterLog newParkCarEnterLog = new ParkCarEnterLog();
                BeanUtils.copyProperties(parkCarEnterLog, newParkCarEnterLog);
                newParkCarEnterLog.setId(SnowFlakeUtil.getId());
                // 判断月租是否过期,过期
                if (monthlyCardInfo.getEndTime().before(new Date()) &&
                        DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()).before(monthlyCardInfo.getEndTime())) {
                    newParkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(monthlyCardInfo.getEndTime()));
                }
                if (new Date().before(monthlyCardInfo.getEndTime())) {
                    newParkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(new Date()));
                }
                newParkCarEnterLog.setCreateTime(new Date());
                newParkCarEnterLog.setCarNature(JddConstant.StringNumber.STRING_ZERO);
                newParkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
                ConfigCarType configCarType = this.getCarType(newParkCarEnterLog.getParkCode(), Integer.valueOf(newParkCarEnterLog.getCarTypeNo()));
                if (null != configCarType) {
                    newParkCarEnterLog.setCarTypeName(configCarType.getCarTypeName());
                    newParkCarEnterLog.setCarTypeId(configCarType.getId());
                }
                newParkCarEnterLog.setMonthlyCardId("");
                newParkCarEnterLog.setParkNumber("");
                parkCarEnterLogs.add(newParkCarEnterLog);
                //组装转卡记录
                MonthlyCarTypeConvert monthlyCarTypeConvert = getMonthlyCarTypeConvert(monthlyCardInfo, parkCarEnterLog, monthlyPackageInfo);
                monthlyCarTypeConverts.add(monthlyCarTypeConvert);
            }

            // 更新车位，插入入场，转卡
            iparkCarEnterLogService.saveBatch(parkCarEnterLogs);
            iMonthlyCarTypeConvertService.saveBatch(monthlyCarTypeConverts);
            editMonthlyCardsVO.setDeleteMonthlyCarTypeConverts(monthlyCarTypeConverts);
            editMonthlyCardsVO.setDeleteParkCarEnterLog(parkCarEnterLogs);
            editMonthlyCardsVO.setDeleteUpdateParkSpaceList(parkSpaceList);
        }
        QueryWrapper<ParkCarMonthly> monthlyQueryWrapper = new QueryWrapper<>();
        monthlyQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
        monthlyQueryWrapper.in("plate_no", plateNos);
        iParkCarMonthlyService.remove(monthlyQueryWrapper);
        editMonthlyCardsVO.setDeleteMonthlyCardId(monthlyCardInfo.getId());
        editMonthlyCardsVO.setDeletePlateNos(plateNos);

    }


    /**
     * 新增入场转卡记录
     *
     * @param monthlyCarDto
     * @return
     */
    public Result addParkCarEnterInfo(MonthlyCardInfo monthlyCarDto, List<ParkSpace> parkSpaceList, List<ParkCarEnterLog> parkCarEnterLogs, EditMonthlyCardsVO editMonthlyCardsVO) {

        log.info("生成月卡时，新增入场记录时传入参数--------------------------》:{}", monthlyCarDto);
        MonthlyPackageInfo monthlyPackageInfo = iMonthlyPackageInfoService.getById(monthlyCarDto.getPackageId());
        List<String> inSitePlateNo = parkCarEnterLogs.stream().map(ParkCarEnterLog::getPlateNo).distinct().collect(Collectors.toList());
        List<String> areaList = parkSpaceList.stream().map(ParkSpace::getAreaId).distinct().collect(Collectors.toList());
        //List<ParkSpace> parkSpaces = this.getFreeSpace(monthlyCarDto.getParkCode(), areaList);
        log.info("生成月卡时，区域信息 --------------------------》:{}", areaList);
        // log.info("开通区域未占用的车位----------------------------》:{}", parkSpaces);

        if (areaList.size() > 1 && inSitePlateNo.size() > 1) {
            return Result.ok("开通成功.多区域的情况下,不允许多车多位的月租车立即生效");
        }
        if (CollectionUtil.isEmpty(inSitePlateNo)) {
            return Result.ok("无空余车位，开通成功");
        }
        TurnCardVo turnCardVo = openGetParkCarEnterLog(monthlyCarDto, inSitePlateNo, parkSpaceList, parkCarEnterLogs, monthlyPackageInfo, editMonthlyCardsVO);
        iparkCarEnterLogService.saveBatch(turnCardVo.getParkCarEnterLogs());
        monthlyCarTypeConvertService.saveBatch(turnCardVo.getMonthlyCarTypeConverts());
        editMonthlyCardsVO.setTurnCardVo(turnCardVo);
        //  parkSpaceService.updateBatchById(turnCardVo.getParkSpaceList());
        return Result.ok("新增成功！");
    }


    /**
     * 转卡记录
     *
     * @param monthlyCardInfo
     * @param plateNos
     * @param notParkSpaces
     * @param parkCarEnterLogs
     * @param monthlyPackageInfo
     * @return
     */
    public TurnCardVo openGetParkCarEnterLog(MonthlyCardInfo monthlyCardInfo, List<String> plateNos, List<ParkSpace> notParkSpaces,
                                             List<ParkCarEnterLog> parkCarEnterLogs, MonthlyPackageInfo monthlyPackageInfo, EditMonthlyCardsVO editMonthlyCardsVO) {
        log.info("进入开通转卡逻辑，传入参数notParkSpaces-----------------》：{}", notParkSpaces);
        TurnCardVo turnCardVo = new TurnCardVo();
        List<ParkCarEnterLog> addParkCarEnterLogs = new ArrayList<>();
        List<MonthlyCarTypeConvert> monthlyCarTypeConverts = new ArrayList<>();
        List<String> areaIdList = notParkSpaces.stream().map(ParkSpace::getAreaId).distinct().collect(Collectors.toList());
        int count = 0;
        if (areaIdList.size() > 1 && plateNos.size() > 1) {
            log.info("多车多位多区域，不处理");
            turnCardVo.setParkCarEnterLogs(addParkCarEnterLogs);
            turnCardVo.setMonthlyCarTypeConverts(monthlyCarTypeConverts);
            return turnCardVo;
        }
        List<ParkSpace> parkSpaceList = new LinkedList<>();
        for (ParkCarEnterLog parkCarEnterLog : parkCarEnterLogs) {
            // 遍历入场纪录，随机分配车位，车位分配完退出
            if (count >= notParkSpaces.size()) {
                log.info("车位分配完退出，循环");
                break;
            }
            // 查询同一辆车的所有入场记录,同一辆车分配同一个车位即可
            if (StringUtils.isBlank(parkCarEnterLog.getParkNumber())) {
                count = dealSamePlateNoPlace(notParkSpaces, parkCarEnterLog, count, areaIdList, monthlyCardInfo, parkSpaceList);
            }
            // 新增入场记录
            parkCarEnterLog.setId(SnowFlakeUtil.getId());
            parkCarEnterLog.setCarTypeId(monthlyPackageInfo.getMonthlyTypeId());
            parkCarEnterLog.setCarTypeName(monthlyPackageInfo.getMonthlyTypeName());
            parkCarEnterLog.setCarNature("1");
            parkCarEnterLog.setEnterType(JddConstant.IntNumber.INT_ZERO);
            parkCarEnterLog.setCreateTime(new Date());
            parkCarEnterLog.setMonthlyCardId(monthlyCardInfo.getId());
            // 若入场时间在月卡开始之后，新增转卡记录，否则，生成欲转卡记录
            if (DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()).after(monthlyCardInfo.getBeginTime())
                    && DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()).before(monthlyCardInfo.getEndTime())) {
                String time = DateUtil.addSecond(parkCarEnterLog.getCarEnterTime(), JddConstant.IntNumber.INT_ONE);
                parkCarEnterLog.setCarEnterTime(time);
                parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
            } else {
                parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_ONE);
                parkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(monthlyCardInfo.getBeginTime()));
            }
            addParkCarEnterLogs.add(parkCarEnterLog);
            MonthlyCarTypeConvert monthlyCarTypeConvert = getMonthlyCarTypeConvert(monthlyCardInfo, parkCarEnterLog, monthlyPackageInfo);
            monthlyCarTypeConverts.add(monthlyCarTypeConvert);
        }
        editMonthlyCardsVO.setDeleteUpdateParkSpaceList(parkSpaceList);
        turnCardVo.setParkCarEnterLogs(addParkCarEnterLogs);
        turnCardVo.setMonthlyCarTypeConverts(monthlyCarTypeConverts);
        return turnCardVo;
    }

    /**
     * 封装转卡信息
     *
     * @param monthlyCardInfo
     * @param parkCarEnterLog
     * @param monthlyPackageInfo
     * @return
     */
    @Override
    public MonthlyCarTypeConvert getMonthlyCarTypeConvert(MonthlyCardInfo monthlyCardInfo, ParkCarEnterLog
            parkCarEnterLog, MonthlyPackageInfo monthlyPackageInfo) {
        MonthlyCarTypeConvert monthlyCarTypeConvert = new MonthlyCarTypeConvert();
        monthlyCarTypeConvert.setId(SnowFlakeUtil.getId());
        monthlyCarTypeConvert.setParkCode(monthlyCardInfo.getParkCode());
        monthlyCarTypeConvert.setParkName(monthlyCardInfo.getParkName());
        monthlyCarTypeConvert.setBatchNumber(parkCarEnterLog.getBatchNumber());
        monthlyCarTypeConvert.setCarEnterId(parkCarEnterLog.getId());
        monthlyCarTypeConvert.setAreaId(parkCarEnterLog.getAreaId());
        monthlyCarTypeConvert.setPlateNo(parkCarEnterLog.getPlateNo());
        monthlyCarTypeConvert.setMonthlyTypeId(monthlyPackageInfo.getMonthlyTypeId());
        monthlyCarTypeConvert.setMonthlyTypeName(monthlyPackageInfo.getMonthlyTypeName());
        monthlyCarTypeConvert.setBeginTime(new Date());
        return monthlyCarTypeConvert;
    }


    /**
     * 注销时 查询绑定月租车车牌号 是否有在场的入场记录
     *
     * @return
     * @author qilina
     */
    private List<ParkCarEnterLog> getPlateNoInPark(String parkCode, String monthlyCardId) {
        // 查询月卡绑定的区域信息和车位信息
        List<ParkCarMonthly> parkCarMonthlyList = getPlateNoInfo(monthlyCardId);
        List<String> areaList = parkCarMonthlyList.stream().map(ParkCarMonthly::getAreaId).distinct().collect(Collectors.toList());
        log.info("查询区域信息，areaList--------------------------》:{}", areaList);
        List<String> plateNos = parkCarMonthlyList.stream().map(ParkCarMonthly::getPlateNo).distinct().collect(Collectors.toList());
        QueryWrapper<ParkCarEnterLog> parkCarEnterLogQueryWrapper = new QueryWrapper<>();
        parkCarEnterLogQueryWrapper.eq("park_code", parkCode);
        parkCarEnterLogQueryWrapper.eq("is_out", JddConstant.StringNumber.STRING_ZERO);
        parkCarEnterLogQueryWrapper.in("plate_no", plateNos);
        parkCarEnterLogQueryWrapper.in("area_id", areaList);
        parkCarEnterLogQueryWrapper.orderByAsc("car_enter_time");
        List<ParkCarEnterLog> list = iparkCarEnterLogService.list(parkCarEnterLogQueryWrapper);
        Map<String, ParkCarEnterLog> newMap = new HashMap(16);
        for (ParkCarEnterLog parkCarEnterLog : list) {
            newMap.put(parkCarEnterLog.getPlateNo(), parkCarEnterLog);
        }
        List<ParkCarEnterLog> carEnterLogs = new ArrayList<>();
        for (String key : newMap.keySet()) {
            carEnterLogs.add(newMap.get(key));
        }
        return carEnterLogs;
    }


    /**
     * 封装日志信息记录日志信息
     *
     * @param monthlyCardInfo
     * @return
     */
    private MonthlyCardEditInfo getMonthlyCardEditInfo(MonthlyCardInfo monthlyCardInfo, String optionsType) {
        //新增月卡延期记录
        MonthlyCardEditInfo monthlyCardEditInfo = new MonthlyCardEditInfo();
        monthlyCardEditInfo.setId(SnowFlakeUtil.getId());
        monthlyCardEditInfo.setParkCode(monthlyCardInfo.getParkCode());
        monthlyCardEditInfo.setParkName(monthlyCardInfo.getParkName());
        monthlyCardEditInfo.setOptionsType(optionsType);
        monthlyCardEditInfo.setMonthlyCardId(monthlyCardInfo.getId());
        monthlyCardEditInfo.setMonthlyCode(monthlyCardInfo.getMonthlyCode());
        monthlyCardEditInfo.setPackageId(monthlyCardInfo.getPackageId());
        monthlyCardEditInfo.setPackageName(monthlyCardInfo.getPackageName());
        monthlyCardEditInfo.setUserName(monthlyCardInfo.getCarOwnerName());
        monthlyCardEditInfo.setMonthlyDepartmentId(monthlyCardInfo.getMonthlyDepartmentId());
        monthlyCardEditInfo.setMonthlyDepartmentName(monthlyCardInfo.getMonthlyDepartmentName());
        monthlyCardEditInfo.setThroughAuthorityId(monthlyCardInfo.getThroughAuthorityId());
        monthlyCardEditInfo.setThroughAuthorityName(monthlyCardInfo.getThroughAuthorityName());
        monthlyCardEditInfo.setBusinessSource(JddConstant.StringNumber.STRING_ONE);
        monthlyCardEditInfo.setRemark(monthlyCardInfo.getRemark());

        Map<String, String> editUserInfoMap = getEditUserInfo(monthlyCardInfo);
        String createUserId = editUserInfoMap.get("createUserId");
        String createUserName = editUserInfoMap.get("createUserName");
        log.info("当前操作人id:{}--name:{}", createUserId, createUserName);

        monthlyCardEditInfo.setCreateUserId(createUserId);
        monthlyCardEditInfo.setCreateUserName(createUserName);

        monthlyCardEditInfo.setCreateTime(new Date());
        monthlyCardEditInfo.setPayTheFee(monthlyCardInfo.getMonthlyMoney());
        MonthlyPackageInfo monthlyPackageInfo = iMonthlyPackageInfoService.getById(monthlyCardInfo.getPackageId());
        monthlyCardEditInfo.setOverdueDelayWay(String.valueOf(monthlyPackageInfo.getOverdueDelayWay()));
        // 不是新增
        if (!JddConstant.StringNumber.STRING_FOUR.equals(optionsType)) {


            QueryWrapper<MonthlyCardEditInfo> monthlyCardEditInfoQueryWrapper = new QueryWrapper<>();
            monthlyCardEditInfoQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
            monthlyCardEditInfoQueryWrapper.orderByDesc("create_time");
            List<MonthlyCardEditInfo> monthlyCardEditInfos = iMonthlyCardEditInfoService.list(monthlyCardEditInfoQueryWrapper);
            monthlyCardEditInfo.setBeforeStartTime(monthlyCardEditInfos.get(0).getStartTime());
            monthlyCardEditInfo.setBeforeEndTime(monthlyCardEditInfos.get(0).getEndTime());
            monthlyCardEditInfo.setBeforeParkNumbers(monthlyCardEditInfos.get(0).getParkNumbers());
            monthlyCardEditInfo.setBeforePlateNos(monthlyCardEditInfos.get(0).getPlateNos());
            log.info("monthlyCardEditInfo=================================>：{}", monthlyCardEditInfo);
            QueryWrapper<ParkCarMonthly> monthlyQueryWrapper = new QueryWrapper<>();
            monthlyQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
            monthlyQueryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
            List<ParkCarMonthly> list = iParkCarMonthlyService.list(monthlyQueryWrapper);
            List<String> plateNos = list.stream().map(ParkCarMonthly::getPlateNo).distinct().collect(Collectors.toList());
            List<String> parkNumbers = list.stream().map(ParkCarMonthly::getParkNumber).distinct().collect(Collectors.toList());
            String plateNo = StringUtils.join(plateNos.toArray(), ",");
            String parkNumber = StringUtils.join(parkNumbers.toArray(), ",");
            // 注销
            if (JddConstant.StringNumber.STRING_THREE.equals(optionsType)) {
                monthlyCardEditInfo.setPayTheFee(monthlyCardInfo.getMonthlyMoney());
                boolean save = iMonthlyCardEditInfoService.save(monthlyCardEditInfo);
                return monthlyCardEditInfo;
            }
            // 修改
            if (JddConstant.StringNumber.STRING_FIVE.equals(optionsType)) {
                monthlyCardEditInfo.setStartTime(monthlyCardEditInfos.get(0).getStartTime());
                monthlyCardEditInfo.setEndTime(monthlyCardEditInfos.get(0).getEndTime());
                monthlyCardEditInfo.setParkNumbers(parkNumber);
                monthlyCardEditInfo.setPlateNos(plateNo);
                boolean save = iMonthlyCardEditInfoService.save(monthlyCardEditInfo);
                return monthlyCardEditInfo;
            }
            // 延期
            if (JddConstant.StringNumber.STRING_TWO.equals(optionsType)) {
                monthlyCardEditInfo.setStartTime(monthlyCardInfo.getBeginTime());
                monthlyCardEditInfo.setEndTime(monthlyCardInfo.getEndTime());
                monthlyCardEditInfo.setParkNumbers(parkNumber);
                monthlyCardEditInfo.setPlateNos(plateNo);
                if (null != monthlyCardInfo.getMonthlyMoney()) {
                    monthlyCardEditInfo.setPayTheFee(monthlyCardInfo.getMonthlyMoney());
                }
                boolean save = iMonthlyCardEditInfoService.save(monthlyCardEditInfo);
                return monthlyCardEditInfo;
            }
        }

        // 新增车牌
        List<String> plateNoList = monthlyCardInfo.getPlateNoList();
        String plateNo = StringUtils.join(plateNoList.toArray(), ",");
        monthlyCardEditInfo.setPlateNos(plateNo);
        // 车位
        List<String> monthlyCardIdList = monthlyCardInfo.getParkNumberList();
        List<String> parkNumbers = new ArrayList<>();
        for (String id : monthlyCardIdList) {
            ParkSpace parkSpace = parkSpaceService.getById(id);
            if (null != parkSpace) {
                parkNumbers.add(parkSpace.getParkNumber());
            }
        }

        String parkNumber = StringUtils.join(parkNumbers.toArray(), ",");
        monthlyCardEditInfo.setParkNumbers(parkNumber);
        monthlyCardEditInfo.setStartTime(monthlyCardInfo.getBeginTime());
        monthlyCardEditInfo.setEndTime(monthlyCardInfo.getEndTime());
        monthlyCardEditInfo.setPaymentChannel(JddConstant.StringNumber.STRING_ONE);
        monthlyCardEditInfo.setPaymentChannel(JddConstant.StringNumber.STRING_ONE);
        log.info("新增操作记录信息:{}", monthlyCardEditInfo);
        boolean save = iMonthlyCardEditInfoService.save(monthlyCardEditInfo);
        return monthlyCardEditInfo;
    }

    /**
     * 获取操作记录操作人信息
     *
     * @param monthlyCardInfo
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author jdd孙庆伟
     * @date 2022/3/9 15:50:41
     * @version 1.0
     */
    public Map<String, String> getEditUserInfo(MonthlyCardInfo monthlyCardInfo) {
        Map<String, String> map = new HashMap<>();
        String createUserId = null;
        String createUserName = null;

        LoginUser sysUser = LoginUserUtils.getLoginUser();

        //如果云端传递的编辑人信息不为空 则操作记录操作人使用云端传递的信息
        if (StringUtils.isNotBlank(monthlyCardInfo.getUpdateUserId()) && StringUtils.isNotBlank(monthlyCardInfo.getUpdateUserName())) {
            createUserId = monthlyCardInfo.getUpdateUserId();
            createUserName = monthlyCardInfo.getUpdateUserName();
        } else {
            //如果为空 使用场端当前登录人信息
            if (sysUser != null) {
                createUserId = sysUser.getId();
                createUserId = sysUser.getUsername();
            } else {
                //如果场端当前登录人也为空，则使用月卡创建人信息
                createUserId = monthlyCardInfo.getCreateUserId();
                createUserName = monthlyCardInfo.getCreateUserName();
            }
        }
        map.put("createUserId", createUserId);
        map.put("createUserName", createUserName);
        return map;
    }

    /**
     * 月卡新信息
     *
     * @param id
     * @return
     */
    public List<ParkCarMonthly> getPlateNoInfo(String id) {
        QueryWrapper<ParkCarMonthly> parkCarMonthlyQueryWrapper = new QueryWrapper<>();
        parkCarMonthlyQueryWrapper.select("DISTINCT(plate_no) AS plateNo", "area_id AS areaId");
        parkCarMonthlyQueryWrapper.eq("monthly_card_id", id);
        List<ParkCarMonthly> parkCarMonthlyList = iParkCarMonthlyService.list(parkCarMonthlyQueryWrapper);
        return parkCarMonthlyList;
    }

    /**
     * 月卡编号生成规则
     *
     * @param parkCode
     * @return
     */
    public String getMonthlyCode(String parkCode) {
        String monthlyCode;
        QueryWrapper<MonthlyCardInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("park_code", parkCode);
        List<MonthlyCardInfo> monthlyCardInfoList = this.list(queryWrapper);
        if (CollectionUtil.isEmpty(monthlyCardInfoList)) {
            return "P000" + 1;
        }
        List<MonthlyCardInfo> monthlyCardInfos = monthlyCardInfoList.stream()
                .sorted(Comparator.comparing(MonthlyCardInfo::getMonthlyCode).reversed())
                .collect(Collectors.toList());
        monthlyCode = monthlyCardInfos.get(0).getMonthlyCode();
        int num = Integer.parseInt(monthlyCode.substring(1));
        num++;
        if (num < 10) {
            monthlyCode = "P000" + num;
        } else if (num >= 10 && num < 100) {
            monthlyCode = "P00" + num;
        } else if (num >= 100 && num < 1000) {
            monthlyCode = "P0" + num;
        } else if (num >= 1000 && num < 10000) {
            monthlyCode = "P" + num;
        } else {
        }
        log.info("生成的新的月卡编号为-------------》:{}", monthlyCode);
        return monthlyCode;
    }

    /**
     * 封装月租车实体信息
     *
     * @param parkSpaces
     * @param plateNoList
     * @param monthlyCardInfo
     * @return
     */
    @Override
    public List<ParkCarMonthly> getParkCarMonthlyEntity(List<ParkSpace> parkSpaces, List<String> plateNoList, MonthlyCardInfo monthlyCardInfo) {
        List<ParkCarMonthly> list = new ArrayList<>();
        ParkCarMonthly parkCarMonthly = new ParkCarMonthly();
        // 查询是否有相关的配置信息
        MonthlyPackageInfo monthlyPackageInfo = iMonthlyPackageInfoService.getById(monthlyCardInfo.getPackageId());
        parkCarMonthly.setId(SnowFlakeUtil.getId());
        parkCarMonthly.setParkCode(monthlyCardInfo.getParkCode());
        parkCarMonthly.setStartTime(monthlyCardInfo.getBeginTime());
        parkCarMonthly.setEndTime(monthlyCardInfo.getEndTime());
        parkCarMonthly.setMonthlyCardId(monthlyCardInfo.getId());
        parkCarMonthly.setParkName(monthlyCardInfo.getParkName());
        parkCarMonthly.setStatus("Y");
        parkCarMonthly.setAddress(monthlyCardInfo.getAddress());
        parkCarMonthly.setMobile(monthlyCardInfo.getTelephone());
        LoginUser sysUser = LoginUserUtils.getLoginUser();
        if (sysUser != null) {
            parkCarMonthly.setCreateUser(sysUser.getRealname());
        }
        parkCarMonthly.setUserName(monthlyCardInfo.getCarOwnerName());
        if (monthlyPackageInfo.getSpaceFlag().equals(JddConstant.IntNumber.INT_TWO)) {
            parkCarMonthly.setIsMulti("Y");
        } else {
            parkCarMonthly.setIsMulti("N");
        }
        for (ParkSpace carPlace : parkSpaces) {
            for (String plateNo : plateNoList) {
                ParkCarMonthly newParkCarMonthly = new ParkCarMonthly();
                BeanUtils.copyProperties(parkCarMonthly, newParkCarMonthly);
                newParkCarMonthly.setId(SnowFlakeUtil.getId());
                newParkCarMonthly.setAreaId(carPlace.getAreaId());
                newParkCarMonthly.setCarTypeId(carPlace.getSpaceType());
                newParkCarMonthly.setAreaName(carPlace.getAreaName());
                newParkCarMonthly.setParkNumber(carPlace.getParkNumber());
                newParkCarMonthly.setPlateNo(plateNo);
                if (null != newParkCarMonthly) {
                    list.add(newParkCarMonthly);
                }
            }
        }
        log.info("生成的月租车位信息为：---------->:{}", list);
        return list;
    }


    /**
     * @param monthlyCardInfo
     * @return
     * @Description 月卡修改
     * @author shangyue
     * @Date 2022-01-19
     */
    @Override
    @Transactional
    public Result<Object> editMonthlyCards(MonthlyCardInfo monthlyCardInfo) {
        try {
            List<ParkSpace> parkSpaceList = monthlyCardInfo.getParkSpaceList();
            if (CollectionUtil.isNotEmpty(parkSpaceList)) {
                parkSpaceList.clear();
            }

            MonthlyCardInfo monthlyCardInfoEntity = this.getById(monthlyCardInfo.getId());
            if (monthlyCardInfoEntity == null) {
                return Result.error("未找到对应月卡信息");
            }
            boolean resFlag = true;
            EditMonthlyCardsVO editMonthlyCardsVO = new EditMonthlyCardsVO();
            // 删除车牌号,走注销逻辑
            List<String> deletePlateNos = monthlyCardInfo.getDeletePlateNos();
            if (CollectionUtil.isNotEmpty(deletePlateNos)) {
                deletePlateNo(deletePlateNos, monthlyCardInfo, editMonthlyCardsVO);
            }
            // 新增车牌号
            List<String> addPlateNo = monthlyCardInfo.getAddPlateNos();
            if (CollectionUtil.isNotEmpty(addPlateNo)) {
                // 查询绑定车位信息
                QueryWrapper<ParkSpace> parkSpaceQueryWrapper = new QueryWrapper<>();
                parkSpaceQueryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
                parkSpaceQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
                List<ParkSpace> spaces = parkSpaceService.list(parkSpaceQueryWrapper);
                log.info("编辑页面，查询绑定车位信息---------------------》:{}", spaces);


                dealInParkCar(spaces, addPlateNo, monthlyCardInfo, editMonthlyCardsVO);
            }
            // 1.修改月卡
            LoginUser loginUser = LoginUserUtils.getLoginUser();
            if (null != loginUser) {
                monthlyCardInfo.setUpdateUserId(loginUser.getUsername());
                monthlyCardInfo.setUpdateUserName(loginUser.getRealname());
            }
            monthlyCardInfo.setUpdateTime(new Date());
            resFlag = this.updateById(monthlyCardInfo);
            editMonthlyCardsVO.setUpdateMonthlyCardInfo(monthlyCardInfo);

            //TODO 返回false说明什么？
            if (!resFlag) {
                return Result.error("修改失败!");
            }
            // 3.新增月卡操作记录
            MonthlyCardEditInfo monthlyCardEditInfo = getMonthlyCardEditInfo(monthlyCardInfo, JddConstant.StringNumber.STRING_FIVE);
            editMonthlyCardsVO.setMonthlyCardEditInfo(monthlyCardEditInfo);
            Result result = monthlyUploadHttpUtils.postMonthlyUpload("", editMonthlyCardsVO);
            if (200 != result.getCode()) {
                throw new JddException(500, result.getMessage());
            }
            return result;
        } catch (Exception e) {
            log.error("处理场端修改月卡信息出现异常,进行数据回滚!-》{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            String messageId = monthlyCardInfo.getMessageId();
            AddMonthlySpace addMonthlySpace = new AddMonthlySpace();
            addMonthlySpace.setStr(messageId);
            monthlyUploadHttpUtils.postMonthlyUpload("", addMonthlySpace);
            return Result.error("月卡修改信息失败!");
        }
    }

    /**
     * 月卡新增
     *
     * @param monthlyCardInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<MonthlyCardInfo> addMonthlyCardInfo(MonthlyCardInfo monthlyCardInfo) {
        Result result = new Result();
        try {
            this.save(monthlyCardInfo);
            AddMonthlyCardInfoVO addMonthlyCardInfoVO = new AddMonthlyCardInfoVO();
            parkSpaceService.updateBatchById(monthlyCardInfo.getParkSpaceList());
            iParkCarMonthlyService.saveBatch(monthlyCardInfo.getParkCarMonthlies());
            iMonthlyCardEditInfoService.save(monthlyCardInfo.getMonthlyCardEditInfo());
            addMonthlyCardInfoVO.setMessageId(monthlyCardInfo.getMessageId());

            addMonthlyCardInfoVO.setMonthlyCardInfoId(monthlyCardInfo.getId());
            QueryWrapper<ParkSpace> parkSpaceQueryWrapper = new QueryWrapper<>();
            parkSpaceQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
            parkSpaceQueryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
            parkSpaceQueryWrapper.eq("park_status", 0);
            List<ParkSpace> parkSpaceList = parkSpaceService.list(parkSpaceQueryWrapper);
            if (CollectionUtils.isEmpty(parkSpaceList)) {
                log.info("当前月卡车位已全被占用！");
                result = monthlyUploadHttpUtils.postMonthlyUpload("", addMonthlyCardInfoVO);
                if (200 != result.getCode()) {
                    throw new JddException(500, result.getMessage());
                }
                return Result.ok("开通成功！");
            }
            MonthlyPackageInfo monthlyPackageInfo = iMonthlyPackageInfoService.getById(monthlyCardInfo.getPackageId());
            List<String> areaList = parkSpaceList.stream().map(ParkSpace::getAreaId).distinct().collect(Collectors.toList());
            if (areaList.size() == 1) {
                // 单区域 一位一车
                if (monthlyPackageInfo.getBindingSpaceNumber() == JddConstant.IntNumber.INT_ONE && monthlyPackageInfo.getBindingCarNumber() == JddConstant.IntNumber.INT_ONE) {
                    result = oneAreaOneSpaceOneCar(monthlyCardInfo, areaList, parkSpaceList, monthlyPackageInfo, addMonthlyCardInfoVO);
                }
                // 单区域 一位多车
                if (monthlyPackageInfo.getBindingSpaceNumber() == JddConstant.IntNumber.INT_ONE && monthlyPackageInfo.getBindingCarNumber() > JddConstant.IntNumber.INT_ONE) {
                    result = oneAreaOneSpaceMoreCar(monthlyCardInfo, areaList, parkSpaceList, monthlyPackageInfo, addMonthlyCardInfoVO);
                }
                // 单区域 多位多车
                if (monthlyPackageInfo.getBindingSpaceNumber() > JddConstant.IntNumber.INT_ONE && monthlyPackageInfo.getBindingCarNumber() > JddConstant.IntNumber.INT_ONE) {
                    result = oneAreaMoreSpaceMoreCar(monthlyCardInfo, areaList, parkSpaceList, monthlyPackageInfo, addMonthlyCardInfoVO);
                }
            } else {
                // 多区域一车
                if (monthlyPackageInfo.getBindingCarNumber() == JddConstant.IntNumber.INT_ONE) {
                    result = moreAreaOneCar(monthlyCardInfo, areaList, parkSpaceList, monthlyPackageInfo, addMonthlyCardInfoVO);
                }
                // 多区域多车
                if (monthlyPackageInfo.getBindingCarNumber() > JddConstant.IntNumber.INT_ONE) {
                }
            }


            result = monthlyUploadHttpUtils.postMonthlyUpload("", addMonthlyCardInfoVO);
            if (200 != result.getCode()) {
                throw new JddException(500, result.getMessage());
            }

        } catch (Exception e) {
            log.error("处理场端新增月卡信息出现异常,进行数据回滚->{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            String messageId = monthlyCardInfo.getMessageId();
            AddMonthlySpace addMonthlySpace = new AddMonthlySpace();
            addMonthlySpace.setStr(messageId);
            monthlyUploadHttpUtils.postMonthlyUpload("", addMonthlySpace);
            return Result.error("新增月卡信息失败!");
        }
        return result;
    }


    /**
     * 多区域一车
     *
     * @param monthlyCardInfo
     * @param areaList
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */
    public Result moreAreaOneCar(MonthlyCardInfo monthlyCardInfo, List<String> areaList, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo, AddMonthlyCardInfoVO addMonthlyCardInfoVO) {
        log.info("=====================开通多区域一车=====================");
        Result result = new Result();
        // 查询入场记录
        QueryWrapper<ParkCarEnterLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
        queryWrapper.eq("is_out", "0");
        queryWrapper.eq("plate_no", monthlyCardInfo.getPlateNoList().get(0));
        queryWrapper.orderByDesc("car_enter_time");
        List<ParkCarEnterLog> enterLogs = iparkCarEnterLogService.list(queryWrapper);
        if (CollectionUtils.isEmpty(enterLogs)) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        if (!areaList.contains(enterLogs.get(0).getAreaId())) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        ParkCarEnterLog parkCarEnterLog = new ParkCarEnterLog();
        BeanUtils.copyProperties(enterLogs.get(0), parkCarEnterLog);
        getTurnAddLog(parkCarEnterLog, monthlyCardInfo, parkSpaceList, monthlyPackageInfo, addMonthlyCardInfoVO);
        result.setResult(addMonthlyCardInfoVO);
        result.setCode(200);
        return result.setMessage("开通成功");
    }


    /**
     * 单区域，多位多车
     *
     * @param monthlyCardInfo
     * @param areaList
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */
    public Result oneAreaMoreSpaceMoreCar(MonthlyCardInfo monthlyCardInfo, List<String> areaList, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo, AddMonthlyCardInfoVO addMonthlyCardInfoVO) {
        log.info("=====================开通单区域多位多车=====================");
        List<String> plateNoList = monthlyCardInfo.getPlateNoList();
        // 查询入场记录
        Result result = new Result();
        List<ParkCarEnterLog> parkCarEnterLogList = getLists(monthlyCardInfo.getParkCode(), plateNoList, areaList.get(0));
        if (CollectionUtils.isEmpty(parkCarEnterLogList)) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        iMonthlyCardInfoService.dealCarLog(parkCarEnterLogList, parkSpaceList, monthlyCardInfo, monthlyPackageInfo, addMonthlyCardInfoVO);
        return Result.ok("开通成功");
    }

    /**
     * 单区域一位多车
     *
     * @param monthlyCardInfo
     * @param areaList
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */
    public Result oneAreaOneSpaceMoreCar(MonthlyCardInfo monthlyCardInfo, List<String> areaList, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo, AddMonthlyCardInfoVO addMonthlyCardInfoVO) {
        log.info("=====================开通单区域一位多车=====================");
        List<String> plateNoList = monthlyCardInfo.getPlateNoList();
        Result result = new Result();
        // 多车牌最近的入场记录入场记录
        List<ParkCarEnterLog> parkCarEnterLogList = getLists(monthlyCardInfo.getParkCode(), plateNoList, areaList.get(0));
        if (CollectionUtils.isEmpty(parkCarEnterLogList)) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        // 下次生效，不转卡
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        ParkCarEnterLog parkCarEnterLog = new ParkCarEnterLog();
        BeanUtils.copyProperties(parkCarEnterLogList.get(0), parkCarEnterLog);
        getTurnAddLog(parkCarEnterLog, monthlyCardInfo, parkSpaceList, monthlyPackageInfo, addMonthlyCardInfoVO);
        result.setResult(addMonthlyCardInfoVO);
        result.setCode(200);
        return result.setMessage("开通成功");
    }

    /**
     * 一车多位，单区域下,最近的一条记录
     *
     * @param parkCode
     * @param plateNos
     * @param areaId
     * @return
     */
    private List<ParkCarEnterLog> getLists(String parkCode, List<String> plateNos, String areaId) {
        QueryWrapper<ParkCarEnterLog> parkCarEnterLogQueryWrapper = new QueryWrapper<>();
        parkCarEnterLogQueryWrapper.eq("park_code", parkCode);
        parkCarEnterLogQueryWrapper.eq("enter_type", 0);
        parkCarEnterLogQueryWrapper.eq("is_out", JddConstant.StringNumber.STRING_ZERO);
        parkCarEnterLogQueryWrapper.in("plate_no", plateNos);
        parkCarEnterLogQueryWrapper.orderByAsc("car_enter_time");
        List<ParkCarEnterLog> parkCarEnterLogList = iparkCarEnterLogService.list(parkCarEnterLogQueryWrapper);
        log.info("办理月卡延期，是否有在场的信息------------------------------》:{}", parkCarEnterLogList);
        Map<String, ParkCarEnterLog> newMap = new HashMap(16);
        for (ParkCarEnterLog parkCarEnterLog : parkCarEnterLogList) {
            newMap.put(parkCarEnterLog.getPlateNo(), parkCarEnterLog);
        }
        List<ParkCarEnterLog> carEnterLogs = new ArrayList<>();
        for (String key : newMap.keySet()) {
            carEnterLogs.add(newMap.get(key));
        }
        List<ParkCarEnterLog> enterLogList = new ArrayList<>();
        for (ParkCarEnterLog parkCarEnterLog : carEnterLogs) {
            if (areaId.equals(parkCarEnterLog.getAreaId())) {
                enterLogList.add(parkCarEnterLog);
            }
        }
        if (CollectionUtils.isEmpty(enterLogList)) {
            return enterLogList;
        }
        List<ParkCarEnterLog> parkCarEnterLogs = enterLogList.stream()
                .sorted(Comparator.comparing(ParkCarEnterLog::getCarEnterTime))
                .collect(Collectors.toList());
        return parkCarEnterLogs;
    }

    /**
     * 单区域一位一车
     *
     * @param monthlyCardInfo
     * @param areaList
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */
    public Result oneAreaOneSpaceOneCar(MonthlyCardInfo monthlyCardInfo, List<String> areaList, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo, AddMonthlyCardInfoVO addMonthlyCardInfoVO) {
        log.info("=====================开通单区域一位一车=====================");
        Result result = new Result();
        List<String> plateNoList = monthlyCardInfo.getPlateNoList();
        // 查询入场记录
        QueryWrapper<ParkCarEnterLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
        queryWrapper.eq("plate_no", plateNoList.get(0));
        queryWrapper.eq("is_out", "0");
        queryWrapper.orderByDesc("car_enter_time");
        List<ParkCarEnterLog> enterLogs = iparkCarEnterLogService.list(queryWrapper);
        if (CollectionUtils.isEmpty(enterLogs)) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        // 下次生效，不转卡
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            result.setResult(addMonthlyCardInfoVO);
            result.setCode(200);
            return result.setMessage("开通成功");
        }
        ParkCarEnterLog parkCarEnterLog = new ParkCarEnterLog();
        // 最近一条记录是否在指定区域
        if (enterLogs.get(0).getAreaId().equals(areaList.get(0))) {
            BeanUtils.copyProperties(enterLogs.get(0), parkCarEnterLog);
            getTurnAddLog(parkCarEnterLog, monthlyCardInfo, parkSpaceList, monthlyPackageInfo, addMonthlyCardInfoVO);
        }
        result.setResult(addMonthlyCardInfoVO);
        result.setCode(200);
        return result.setMessage("开通成功");

    }


    /**
     * 单区域 一位 新增入场记录
     *
     * @param parkCarEnterLog
     * @param monthlyCardInfo
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */

    private void getTurnAddLog(ParkCarEnterLog parkCarEnterLog, MonthlyCardInfo monthlyCardInfo, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo, AddMonthlyCardInfoVO addMonthlyCardInfoVO) {
        // 开过期月租，在场车辆的入场时间在月租结束时间之后，不处理
        if (monthlyCardInfo.getEndTime().before(DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()))) {
            return;
        }

        parkCarEnterLog.setId(SnowFlakeUtil.getId());
        parkCarEnterLog.setParkNumber(parkSpaceList.get(0).getParkNumber());
        parkCarEnterLog.setCarNature("1");
        parkCarEnterLog.setCarTypeId(monthlyPackageInfo.getMonthlyTypeId());
        parkCarEnterLog.setCarTypeName(monthlyPackageInfo.getMonthlyTypeName());
        parkCarEnterLog.setMonthlyCardId(monthlyCardInfo.getId());
        parkCarEnterLog.setCreateTime(new Date());
        parkCarEnterLog.setEnterType(JddConstant.IntNumber.INT_ZERO);
        // 若入场时间在月卡开始之后，新增转卡记录，否则，生成欲转卡记录
        if (DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()).after(monthlyCardInfo.getBeginTime())
                && DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()).before(monthlyCardInfo.getEndTime())) {
            String time = DateUtil.addSecond(parkCarEnterLog.getCarEnterTime(), JddConstant.IntNumber.INT_ONE);
            parkCarEnterLog.setCarEnterTime(time);
            parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
        } else {
            parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_ONE);
            parkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(monthlyCardInfo.getBeginTime()));
        }

        // 更新车位信息
        parkSpaceList.get(0).setPlateNo(parkCarEnterLog.getPlateNo());
        parkSpaceList.get(0).setParkStatus("1");
        parkSpaceService.updateById(parkSpaceList.get(0));
        List<ParkSpace> lists = new ArrayList<>();
        lists.add(parkSpaceList.get(0));
        addMonthlyCardInfoVO.setUpdateParkSpace(lists);
        log.info("待插入入场记录---------------->:{}", parkCarEnterLog);

        iparkCarEnterLogService.save(parkCarEnterLog);
        addMonthlyCardInfoVO.setParkCarEnterLog(parkCarEnterLog);
        MonthlyCarTypeConvert monthlyCarTypeConvert = iMonthlyCardInfoService.getMonthlyCarTypeConvert(monthlyCardInfo, parkCarEnterLog, monthlyPackageInfo);
        iMonthlyCarTypeConvertService.save(monthlyCarTypeConvert);
        addMonthlyCardInfoVO.setMonthlyCarTypeConvert(monthlyCarTypeConvert);
    }


    /**
     * 月卡延期
     *
     * @param monthlyCardEditInfoVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result issueUpdateMonthlyCardDelay(MonthlyCardEditInfoVO monthlyCardEditInfoVO) {
        try {
            MonthlyCardDelayVO monthlyCardDelayVO = new MonthlyCardDelayVO();

            MonthlyCardInfo monthlyCardInfo = monthlyCardEditInfoVO.getMonthlyCardInfo();

            MonthlyCardInfo newMonthlyCardInfo = iMonthlyCardInfoService.getById(monthlyCardInfo.getId());
            MonthlyCardEditInfo monthlyCardEditInfo = monthlyCardInfo.getMonthlyCardEditInfo();

            iMonthlyCardEditInfoService.save(monthlyCardEditInfo);
            List<ParkCarMonthly> parkCarMonthlies = monthlyCardEditInfoVO.getParkCarMonthlies();
            boolean resFlag = false;
            resFlag = this.updateById(monthlyCardEditInfoVO.getMonthlyCardInfo());

            if (!resFlag) {
                return Result.error("更新monthlyCardInfo失败！");
            }
            List<ParkSpace> parskSpaceList = monthlyCardEditInfoVO.getParskSpaceList();
            if (CollectionUtils.isNotEmpty(parskSpaceList)) {
                resFlag = parkSpaceService.updateBatchById(parskSpaceList);
            }

            if (!resFlag) {
                return Result.error("更新parskSpace失败！");
            }
            resFlag = iParkCarMonthlyService.updateBatchById(monthlyCardEditInfoVO.getParkCarMonthlies());
            if (!resFlag) {
                return Result.error("更新parkCarMonthlys失败！");
            }
            monthlyCardDelayVO.setMonthlyCardInfoId(monthlyCardInfo.getId());
            monthlyCardDelayVO.setMessageId(monthlyCardEditInfoVO.getMessageId());
            List<String> plateNos = parkCarMonthlies.stream().map(ParkCarMonthly::getPlateNo).distinct().collect(Collectors.toList());
            List<String> areaList = parkCarMonthlies.stream().map(ParkCarMonthly::getAreaId).distinct().collect(Collectors.toList());
            // 是否有未占用车位
            QueryWrapper<ParkSpace> parkSpaceQueryWrapper = new QueryWrapper<>();
            parkSpaceQueryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
            parkSpaceQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
            List<ParkSpace> parkSpaces = parkSpaceService.list(parkSpaceQueryWrapper);

            MonthlyPackageInfo packageInfo = iMonthlyPackageInfoService.getById(monthlyCardInfo.getPackageId());

            // 在场车辆查询
            List<ParkCarEnterLog> parkCarEnterLogs = getList(monthlyCardInfo.getParkCode(), plateNos, areaList);

            log.info("办理月卡延期，需要转卡的在场信息------------------------------》:{}", parkCarEnterLogs);
            if (CollectionUtil.isEmpty(parkCarEnterLogs)) {
                monthlyUploadHttpUtils.postMonthlyUpload("", monthlyCardDelayVO);
                return Result.ok("延期成功！");
            }
            List<MonthlyCarTypeConvert> monthlyCarTypeConverts = new ArrayList<>();
            int count = 0;
            List<ParkCarEnterLog> parkCarEnterLogList = new LinkedList<>();
            List<ParkSpace> parkSpaceList = new LinkedList<>();
            for (ParkCarEnterLog parkCarEnterLog : parkCarEnterLogs) {

                // 开过期月租，在场车辆的入场时间在月租结束时间之后，不处理
                if (monthlyCardInfo.getEndTime().before(DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()))) {
                    continue;
                }

                if ("1".equals(parkCarEnterLog.getCarNature())) {
                    log.info("---------进入月租车入场延期转卡逻辑---------");

                    if (packageInfo.getOverdueDelayWay() == JddConstant.IntNumber.INT_ONE) {
                        log.info("---------月租车入场顺延不转卡>continue----------");
                        continue;
                    }

                    if (new Date().before(newMonthlyCardInfo.getEndTime())) {
                        log.info("---------非过期跳延等于顺延>continue---------");
                        continue;
                    }

                    log.info("---------进入跳延处理逻辑---------");
                    parkCarEnterLog.setId(SnowFlakeUtil.getId());
                    parkCarEnterLog.setCarNature(JddConstant.StringNumber.STRING_ONE);
                    parkCarEnterLog.setCarTypeName(packageInfo.getMonthlyTypeName());
                    parkCarEnterLog.setCarTypeId(packageInfo.getMonthlyTypeId());
                    parkCarEnterLog.setEnterType(JddConstant.IntNumber.INT_ZERO);
                    parkCarEnterLog.setCreateTime(new Date());
                    dealDelayLogs(parkCarEnterLogList, monthlyCardInfo, parkCarEnterLog, newMonthlyCardInfo, packageInfo);
                    MonthlyCarTypeConvert monthlyCarTypeConvert = iMonthlyCardInfoService.getMonthlyCarTypeConvert(monthlyCardInfo, parkCarEnterLog, packageInfo);
                    monthlyCarTypeConverts.add(monthlyCarTypeConvert);
                    continue;
                }

                // 临时车入场的车
                if ("0".equals(parkCarEnterLog.getCarNature())) {

                    log.info("---------临时车入场车辆分配车位---------");
                    // 临时车分配车位，月租车无需分配车位
                   dealSamePlateNoPlace(parkSpaces, parkCarEnterLog, count, areaList, monthlyCardInfo, parkSpaceList);
                }

                // 新增入场记录
                parkCarEnterLog.setId(SnowFlakeUtil.getId());
                parkCarEnterLog.setCarNature(JddConstant.StringNumber.STRING_ONE);
                parkCarEnterLog.setCarTypeName(packageInfo.getMonthlyTypeName());
                parkCarEnterLog.setCarTypeId(packageInfo.getMonthlyTypeId());
                parkCarEnterLog.setEnterType(JddConstant.IntNumber.INT_ZERO);
                parkCarEnterLog.setCreateTime(new Date());

                // 如果顺延，插入入场记录入场时间加1s，车辆类型为月租车
                if (packageInfo.getOverdueDelayWay() == JddConstant.IntNumber.INT_ONE) {
                    log.info("---------进入顺延处理逻辑，插入入场记录入场时间加1s，车辆类型为月租车---------");
                    String time = DateUtil.addSecond(parkCarEnterLog.getCarEnterTime(), JddConstant.IntNumber.INT_ONE);
                    parkCarEnterLog.setCarEnterTime(time);
                    parkCarEnterLog.setMonthlyCardId(monthlyCardInfo.getId());
                    parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
                    // 还原原入场记录的车位编号
                    iparkCarEnterLogService.save(parkCarEnterLog);
                    parkCarEnterLogList.add(parkCarEnterLog);
                } else {
                    log.info("---------进入跳延处理逻辑---------");

                    if (new Date().before(newMonthlyCardInfo.getEndTime())) {
                        log.info("---------过期跳延，进入顺延处理逻辑---------");
                        String time = DateUtil.addSecond(parkCarEnterLog.getCarEnterTime(), JddConstant.IntNumber.INT_ONE);
                        parkCarEnterLog.setCarEnterTime(time);
                        parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
                        parkCarEnterLog.setMonthlyCardId(monthlyCardInfo.getId());
                        parkCarEnterLogList.add(parkCarEnterLog);
                    } else {
                        log.info("---------未过期跳延期,进入跳延处理逻辑---------");
                        dealDelayLogs(parkCarEnterLogList, monthlyCardInfo, parkCarEnterLog, newMonthlyCardInfo, packageInfo);
                        MonthlyCarTypeConvert monthlyCarTypeConvert = getMonthlyCarTypeConvert(monthlyCardInfo, parkCarEnterLog, packageInfo);
                        monthlyCarTypeConverts.add(monthlyCarTypeConvert);
                    }

                }
            }

            monthlyCardDelayVO.setParkCarEnterLogList(parkCarEnterLogList);
            monthlyCardDelayVO.setParkSpaceList(parkSpaceList);
            monthlyCardDelayVO.setMonthlyCarTypeConverts(monthlyCarTypeConverts);
            resFlag = monthlyCarTypeConvertService.saveBatch(monthlyCarTypeConverts);
            if (!resFlag) {
                return Result.error("新增转卡记录失败");
            }
            Result result = monthlyUploadHttpUtils.postMonthlyUpload("", monthlyCardDelayVO);
            if (200 == result.getCode()) {
                return result;
            }
            //如果云端同步失败主动抛出异常
            throw new JddException(500, result.getMessage());
        } catch (Exception e) {
            log.error("处理场端延期月卡信息出现异常,进行数据回滚->{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            String messageId = monthlyCardEditInfoVO.getMessageId();
            AddMonthlySpace addMonthlySpace = new AddMonthlySpace();
            addMonthlySpace.setStr(messageId);
            monthlyUploadHttpUtils.postMonthlyUpload("", addMonthlySpace);
            return Result.error("延期月卡信息失败!");
        }
    }


}
